home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Tools - Objects / MacApp / MacApp CD Release / MacApp 2.0.1 (Many Libraries) / Examples / Calc / USynchScroller.inc1.p < prev    next >
Encoding:
Text File  |  1990-10-25  |  12.5 KB  |  461 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { USynchScroller.inc1.p }
  4. { Copyright © 1989-1990 by Apple Computer Inc. All rights reserved. }
  5.  
  6. {--------------------------------------------------------------------------------------------------}
  7. {$S AInit}
  8.  
  9. PROCEDURE InitUSynchScroller;
  10.  
  11.     BEGIN
  12.     IF qTemplateViews THEN
  13.         BEGIN
  14.         { Suppress Linker dead-stripping of these classes }
  15.         IF gDeadStripSuppression THEN
  16.             BEGIN
  17.             IF Member(TObject(NIL), TSynchScroller) THEN;
  18.             IF Member(TObject(NIL), TPrimaryScroller) THEN;
  19.             IF Member(TObject(NIL), TSecondaryScroller) THEN;
  20.             END;
  21.         END;
  22.     END;
  23.  
  24. {****************************************************************************************}
  25. {  T S y n c h S c r o l l e r    }
  26. {****************************************************************************************}
  27. {$S ARes}
  28.  
  29. PROCEDURE TSynchScroller.IRes(itsDocument: TDocument;
  30.                               itsSuperview: TView;
  31.                               VAR itsParams: Ptr); OVERRIDE;
  32.  
  33.     BEGIN
  34.     fLimiting := FALSE;
  35.  
  36.     INHERITED IRes(itsDocument, itsSuperview, itsParams);
  37.     END;
  38.  
  39. {--------------------------------------------------------------------------------------------------}
  40. {$S ARes}
  41.  
  42. PROCEDURE TSynchScroller.SetScrollLimits(scrollLimit: VPoint;
  43.                                          drawScrollBars: BOOLEAN); OVERRIDE;
  44.  
  45.     VAR
  46.         wasLimiting:        BOOLEAN;
  47.         fi:                 FailInfo;
  48.  
  49.     PROCEDURE HdlSetScrollLimits(error: OSErr;
  50.                                  message: LONGINT);
  51.  
  52.         BEGIN
  53.         fLimiting := wasLimiting;
  54.         END;
  55.  
  56.     BEGIN
  57.     wasLimiting := fLimiting;
  58.     fLimiting := TRUE;
  59.     CatchFailures(fi, HdlSetScrollLimits);
  60.     INHERITED SetScrollLimits(scrollLimit, drawScrollBars);
  61.     Success(fi);
  62.     fLimiting := wasLimiting;
  63.     END;
  64.  
  65. {--------------------------------------------------------------------------------------------------}
  66. {$S AFields}
  67.  
  68. PROCEDURE TSynchScroller.Fields(PROCEDURE DoToField(fieldName: Str255;
  69.                                                     fieldAddr: Ptr;
  70.                                                     fieldType: INTEGER)); OVERRIDE;
  71.  
  72.     BEGIN
  73.     DoToField('TSynchScroller', NIL, bClass);
  74.     DoToField('fLimiting', @fLimiting, bBoolean);
  75.  
  76.     INHERITED Fields(DoToField);
  77.     END;
  78.  
  79. {****************************************************************************************}
  80. {  T P r i m a r y S c r o l l e r    }
  81. {****************************************************************************************}
  82. {$S ARes}
  83.  
  84. PROCEDURE TPrimaryScroller.IRes(itsDocument: TDocument;
  85.                                 itsSuperview: TView;
  86.                                 VAR itsParams: Ptr); OVERRIDE;
  87.  
  88.     BEGIN
  89.     fSecondaryScrollers := NIL;
  90.     INHERITED IRes(itsDocument, itsSuperview, itsParams);
  91.     END;
  92.  
  93. {--------------------------------------------------------------------------------------------------}
  94. {$S ARes}
  95.  
  96. PROCEDURE TPrimaryScroller.Free; OVERRIDE;
  97.  
  98.     BEGIN
  99.     FreeIfObject(fSecondaryScrollers);                    { Next release this becomes a function that
  100.                                                          returns nil. I'm getting sick of nilling
  101.                                                          references by hand afterwards. Thanks for
  102.                                                          the suggestion LT! }
  103.     fSecondaryScrollers := NIL;
  104.     INHERITED Free;
  105.     END;
  106.  
  107. {--------------------------------------------------------------------------------------------------}
  108. {$S ARes}
  109.  
  110. PROCEDURE TPrimaryScroller.AddSecondaryScroller(itsSecondaryScroller: TSecondaryScroller;
  111.                                                 itsHDependency, itsVDependency: VCoordinate);
  112.  
  113.     BEGIN
  114.     IF itsSecondaryScroller <> NIL THEN
  115.         BEGIN
  116.         WITH itsSecondaryScroller DO
  117.             BEGIN
  118.             fPrimaryScroller := SELF;                    { !!! Really should give notification by
  119.                                                          something like BeWithPrimaryScroller. }
  120.             WITH fDeltaFactor DO
  121.                 BEGIN
  122.                 h := itsHDependency;
  123.                 v := itsVDependency;
  124.                 END;
  125.             END;
  126.  
  127.         IF fSecondaryScrollers = NIL THEN
  128.             fSecondaryScrollers := NewList;
  129.  
  130.         fSecondaryScrollers.Insert(itsSecondaryScroller);
  131.  
  132.         END;
  133.     END;
  134.  
  135. {--------------------------------------------------------------------------------------------------}
  136. {$S ARes}
  137.  
  138. PROCEDURE TPrimaryScroller.RemoveSecondaryScroller(itsSecondaryScroller: TSecondaryScroller);
  139.  
  140.     BEGIN
  141.     IF itsSecondaryScroller <> NIL THEN
  142.         WITH itsSecondaryScroller DO
  143.             BEGIN
  144.             fPrimaryScroller := NIL;                    { !!! Really should give notification by
  145.                                                          something like BeInPrimaryScroller. }
  146.  
  147.             IF fSecondaryScrollers <> NIL THEN
  148.                 BEGIN
  149.                 fSecondaryScrollers.Delete(itsSecondaryScroller);
  150.                 IF fSecondaryScrollers.IsEmpty THEN     { !!! TViews should be this nice with
  151.                                                          subview lists }
  152.                     BEGIN
  153.                     FreeIfObject(fSecondaryScrollers);
  154.                     fSecondaryScrollers := NIL;
  155.                     END;
  156.                 END;
  157.  
  158.             END;
  159.  
  160.     END;
  161.  
  162. {--------------------------------------------------------------------------------------------------}
  163. {$S ARes}
  164.  
  165. PROCEDURE TPrimaryScroller.DoScroll(delta: VPoint;
  166.                                     redraw: BOOLEAN); OVERRIDE;
  167.  
  168.     PROCEDURE SynchDependents(aSecondaryScroller: TSecondaryScroller);
  169.  
  170.         BEGIN
  171.         WITH aSecondaryScroller DO
  172.             BEGIN
  173.             IF fDeltaFactor.h <> 0 THEN
  174.                 fTranslation.h := fTranslation.h + delta.h;
  175.  
  176.             IF fDeltaFactor.v <> 0 THEN
  177.                 fTranslation.v := fTranslation.v + delta.v;
  178.  
  179.             IF NOT EqualPt(fDeltaFactor, gZeroPt) THEN
  180.                 InvalidateFocus;                        { You never know who might call }
  181.             END;
  182.         END;
  183.  
  184.     BEGIN
  185.     INHERITED DoScroll(delta, redraw);
  186.     IF NOT (fLimiting | redraw) THEN                    { If invoked by SetScrollLimits, don't
  187.                                                          affect peer scrollers }
  188.         IF fSecondaryScrollers <> NIL THEN
  189.             fSecondaryScrollers.Each(SynchDependents)
  190.     END;
  191.  
  192. {--------------------------------------------------------------------------------------------------}
  193. {$S ARes}
  194.  
  195. PROCEDURE TPrimaryScroller.ScrollDraw(delta: VPoint;
  196.                                       invalidate: BOOLEAN); OVERRIDE;
  197.  
  198.     VAR
  199.         superVisRect:        Rect;
  200.         myVFrame:            VRect;
  201.         myQDFrame:            Rect;
  202.         fi:                 FailInfo;
  203.         fi2:                 FailInfo;
  204.         theScrollRgn:        RgnHandle;
  205.         {$IFC qExperimentalAndUnsupported}
  206.         oldgEnableDoubleBuffering: Boolean;
  207.         {$EndC}
  208.  
  209.     PROCEDURE HdlScrollDraw(error: OSErr;
  210.                             message: LONGINT);
  211.  
  212.         BEGIN
  213.         IF theScrollRgn <> NIL THEN
  214.             DisposeRgn(theScrollRgn);
  215.         theScrollRgn := NIL;
  216.         END;
  217.  
  218.     PROCEDURE HdlDoScrollDraw(error: OSErr;
  219.                             message: LONGINT);
  220.  
  221.         BEGIN
  222.         {$IFC qExperimentalAndUnsupported}
  223.         gEnableDoubleBuffering := oldgEnableDoubleBuffering;
  224.         {$EndC}
  225.         END;
  226.  
  227.     PROCEDURE SynchDependents(aSecondaryScroller: TSecondaryScroller);
  228.  
  229.         BEGIN
  230.         WITH aSecondaryScroller DO
  231.             BEGIN
  232.             IF fDeltaFactor.h <> 0 THEN
  233.                 fTranslation.h := fTranslation.h + delta.h;
  234.  
  235.             IF fDeltaFactor.v <> 0 THEN
  236.                 fTranslation.v := fTranslation.v + delta.v;
  237.             END;
  238.         END;
  239.  
  240.     PROCEDURE ForceRedrawDependents(aSecondaryScroller: TSecondaryScroller);
  241.     { Force the redraw if we're dependent on the direction }
  242.  
  243.         BEGIN
  244.         WITH aSecondaryScroller DO
  245.             BEGIN
  246.             IF (delta.v <> 0) & (fDeltaFactor.v <> 0) THEN
  247.                 ForceRedraw
  248.             ELSE IF (delta.h <> 0) & (fDeltaFactor.h <> 0) THEN
  249.                 ForceRedraw;
  250.             END;
  251.         END;
  252.  
  253.     PROCEDURE ScrollDependents(aSecondaryScroller: TSecondaryScroller);
  254.     { Scroll the dependents if they're not }
  255.  
  256.         VAR
  257.             frameVRect:         VRect;
  258.             frameRect:            Rect;
  259.  
  260.         BEGIN
  261.         WITH aSecondaryScroller DO
  262.             BEGIN
  263.             { !!! with additional tests we could also support scrollers in other superviews
  264.             and non-matching extents and scrollLimits in the pertinent axis by simply calling
  265.             their scrolling methods.  This would be nice for synchronized windows. }
  266.             GetFrame(frameVRect);
  267.             fSuperView.ViewToQDRect(frameVRect, frameRect);
  268.             IF (delta.h <> 0) & (delta.v <> 0) & (fDeltaFactor.h = kNotHDependent) &
  269.                (fDeltaFactor.v <> kNotVDependent) THEN { main scroller is moving both directions
  270.                                                          but dependent can only move in v }
  271.                 BEGIN
  272.                 ScrollRect(frameRect, 0, - delta.v, gTempRgn);
  273.                 InvalRgn(gTempRgn);
  274.                 END
  275.             ELSE IF (delta.h <> 0) & (delta.v <> 0) & (fDeltaFactor.h <> kNotHDependent) &
  276.                     (fDeltaFactor.v = kNotVDependent) THEN { main scroller is moving both
  277.                                                              directions but dependent can only move
  278.                                                              in h }
  279.                 BEGIN
  280.                 ScrollRect(frameRect, - delta.h, 0, gTempRgn);
  281.                 InvalRgn(gTempRgn);
  282.                 END
  283.             ELSE IF ((delta.h <> 0) & (fDeltaFactor.h <> kNotHDependent)) | ((delta.v <> 0) &
  284.                     (fDeltaFactor.v <> kNotVDependent)) THEN { main scroller is moving in either
  285.                                                                direction and dependent can follow }
  286.                 BEGIN
  287.                 RectRgn(gTempRgn, frameRect);
  288.                 UnionRgn(theScrollRgn, gTempRgn, theScrollRgn);
  289.                 END;
  290.             END;
  291.         END;
  292.  
  293.     PROCEDURE DoScrollDraw;
  294.  
  295.         VAR
  296.             aPoint: Point;
  297.             aWindow: TWindow;
  298.             theUpdateRgn: RgnHandle;
  299.  
  300.         BEGIN
  301.         theScrollRgn := NIL;
  302.         CatchFailures(fi, HdlScrollDraw);
  303.         theScrollRgn := MakeNewRgn;
  304.  
  305.         GetFrame(myVFrame);
  306.         fSuperView.ViewToQDRect(myVFrame, myQDFrame);
  307.         RectRgn(theScrollRgn, myQDFrame);
  308.  
  309.         fSuperView.GetVisibleRect(superVisRect);
  310.  
  311.         IF gIntenseDebugging THEN
  312.             BEGIN
  313.             WrLblRect('             superVisRect', superVisRect);
  314.             WRITELN;
  315.             WrLblVPt('          gLongOffset', gLongOffset);
  316.             WRITELN;
  317.             END;
  318.  
  319.         IF fSecondaryScrollers <> NIL THEN
  320.             fSecondaryScrollers.Each(SynchDependents);
  321.  
  322.         IF (ABS(delta.h) > kMaxCoord) | (ABS(delta.v) > kMaxCoord) THEN
  323.             BEGIN                                        { Too far to use ScrollRect }
  324.  
  325.             ForceRedraw;
  326.  
  327.             IF fSecondaryScrollers <> NIL THEN
  328.                 fSecondaryScrollers.Each(ForceRedrawDependents);
  329.  
  330.             END
  331.         ELSE
  332.             BEGIN                                        { Can use ScrollRect }
  333.             {$IFC qDebug}
  334.             UseTempRgn('TPrimaryScroller.ScrollDraw');
  335.             {$ENDC}
  336.  
  337.             IF fSecondaryScrollers <> NIL THEN
  338.                 fSecondaryScrollers.Each(ScrollDependents);
  339.  
  340.             IF qDebug THEN
  341.                 fSuperView.AssumeFocused;
  342.  
  343.             { Now, we've either scrolled any dependent scrollers that can't scroll with
  344.             us or we've accumulated their frames in theScrollRgn.  By clipping to the
  345.             accumulated region we can just scroll the entire superview and the right
  346.             stuff should happen. (Cross fingers) }
  347.  
  348.             RectRgn(gTempRgn, superVisRect);
  349.             SectRgn(theScrollRgn, gTempRgn, theScrollRgn);
  350.             SetClip(theScrollRgn);
  351.  
  352.             { If we're in a window then remove the update area from the clipRgn since it contains
  353.             stale bits and it's no use to move them (in fact it's damaging) }
  354.             aWindow := GetWindow;
  355.             if aWindow <> NIL THEN
  356.                 BEGIN
  357.                 theUpdateRgn := WindowPeek(aWindow.fWMgrWindow)^.updateRgn;
  358.                 if not EmptyRgn(theUpdateRgn) THEN
  359.                     begin
  360.  
  361.                     { The update region is in global coords but the clip is in local coords.
  362.                     Offset the region to make it in local coords here and restore it there
  363.                     to save copying it }
  364.                     aPoint := gZeroPt;
  365.                     LocalToGlobal(aPoint);
  366.                     OffsetRgn(theUpdateRgn, -aPoint.h,-aPoint.v);
  367.     
  368.                     DiffRgn(thePort^.clipRgn, theUpdateRgn, gTempRgn);
  369.  
  370.                     OffsetRgn(theUpdateRgn, aPoint.h,aPoint.v);
  371.  
  372.                     SetClip(gTempRgn);
  373.                     END;
  374.                 END;
  375.     
  376.             ScrollRect(superVisRect, - delta.h, - delta.v, gTempRgn);
  377.             InvalRgn(gTempRgn);
  378.  
  379.             {$IFC qDebug}
  380.             DoneWithTempRgn;
  381.             {$ENDC}
  382.             END;
  383.  
  384.         DisposeRgn(theScrollRgn);
  385.         theScrollRgn := NIL;
  386.  
  387.         Success(fi);
  388.         END;
  389.  
  390.     BEGIN
  391.     IF FocusOnSuperView & fSuperView.IsVisible THEN
  392.         BEGIN
  393.         {$IFC qExperimentalAndUnsupported}
  394.         IF gEnableDoubleBuffering & NOT (gPrinting | gDrawingPictScrap) THEN
  395.             BEGIN
  396.             oldgEnableDoubleBuffering := gEnableDoubleBuffering;
  397.             gEnableDoubleBuffering := FALSE;        { so subviews won't attempt to do off screen
  398.                                                      }
  399.             CatchFailures(fi2, HdlDoScrollDraw);
  400.             fSuperView.DoOffScreen(DoScrollDraw);
  401.             Success(fi2);
  402.             gEnableDoubleBuffering := oldgEnableDoubleBuffering;
  403.             END
  404.         ELSE
  405.             DoScrollDraw;
  406.         {$ELSEC}
  407.         DoScrollDraw;
  408.         {$EndC}
  409.  
  410.         IF qExperimentalAndUnsupported | NOT invalidate THEN
  411.             fSuperView.Update
  412.         ELSE
  413.             fSuperView.InvalidateFocus;
  414.         END;
  415.  
  416.     END;
  417. {--------------------------------------------------------------------------------------------------}
  418. {$S AFields}
  419.  
  420. PROCEDURE TPrimaryScroller.Fields(PROCEDURE DoToField(fieldName: Str255;
  421.                                                       fieldAddr: Ptr;
  422.                                                       fieldType: INTEGER)); OVERRIDE;
  423.  
  424.     BEGIN
  425.     DoToField('TPrimaryScroller', NIL, bClass);
  426.     DoToField('fSecondaryScrollers', @fSecondaryScrollers, bObject);
  427.  
  428.     INHERITED Fields(DoToField);
  429.     END;
  430.  
  431. {****************************************************************************************}
  432. {  T S e c o n d a r y S c r o l l e r    }
  433. {****************************************************************************************}
  434. {$S ARes}
  435.  
  436. PROCEDURE TSecondaryScroller.DoScroll(delta: VPoint;
  437.                                       redraw: BOOLEAN); OVERRIDE;
  438.  
  439.     BEGIN
  440.     IF fLimiting THEN                                    { Invoked by SetScrollLimits, so don't
  441.                                                          affect peer scrollers }
  442.         INHERITED DoScroll(delta, redraw)
  443.     ELSE
  444.         fPrimaryScroller.ScrollBy(fDeltaFactor.h * delta.h, fDeltaFactor.v * delta.v, redraw);
  445.     END;
  446.  
  447. {--------------------------------------------------------------------------------------------------}
  448. {$S AFields}
  449.  
  450. PROCEDURE TSecondaryScroller.Fields(PROCEDURE DoToField(fieldName: Str255;
  451.                                                         fieldAddr: Ptr;
  452.                                                         fieldType: INTEGER)); OVERRIDE;
  453.  
  454.     BEGIN
  455.     DoToField('TSecondaryScroller', NIL, bClass);
  456.     DoToField('fPrimaryScroller', @fPrimaryScroller, bObject);
  457.     DoToField('fDeltaFactor', @fDeltaFactor, bPoint);
  458.  
  459.     INHERITED Fields(DoToField);
  460.     END;
  461.